home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / hplip / ui4 / setupdialog.py < prev    next >
Encoding:
Python Source  |  2011-12-02  |  46.9 KB  |  1,297 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2001-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Authors: Don Welch
  20. #
  21.  
  22. # StdLib
  23. import socket
  24. import operator
  25.  
  26. # Local
  27. from base.g import *
  28. from base import device, utils, models, pkit
  29. from prnt import cups
  30. from base.codes import *
  31. from ui_utils import *
  32. #from installer import core_install
  33. from installer.core_install import CoreInstall
  34.  
  35. # Qt
  36. from PyQt4.QtCore import *
  37. from PyQt4.QtGui import *
  38.  
  39. # Ui
  40. from setupdialog_base import Ui_Dialog
  41. from plugindialog import PluginDialog
  42. from wifisetupdialog import WifiSetupDialog, SUCCESS_CONNECTED
  43.  
  44. # Fax
  45. try:
  46.     from fax import fax
  47.     fax_import_ok = True
  48. except ImportError:
  49.     # This can fail on Python < 2.3 due to the datetime module
  50.     fax_import_ok = False
  51.     log.warning("Fax setup disabled - Python 2.3+ required.")
  52.  
  53.  
  54. PAGE_DISCOVERY = 0
  55. PAGE_DEVICES = 1
  56. PAGE_ADD_PRINTER = 2
  57. PAGE_REMOVE = 3
  58.  
  59.  
  60. BUTTON_NEXT = 0
  61. BUTTON_FINISH = 1
  62. BUTTON_ADD_PRINTER = 2
  63. BUTTON_REMOVE = 3
  64.  
  65. ADVANCED_SHOW = 0
  66. ADVANCED_HIDE = 1
  67.  
  68. DEVICE_DESC_ALL = 0
  69. DEVICE_DESC_SINGLE_FUNC = 1
  70. DEVICE_DESC_MULTI_FUNC = 2
  71.  
  72.  
  73.  
  74.  
  75.  
  76. class PasswordDialog(QDialog):
  77.     def __init__(self, prompt, parent=None, name=None, modal=0, fl=0):
  78.         QDialog.__init__(self, parent)
  79.         self.prompt = prompt
  80.  
  81.         Layout= QGridLayout(self)
  82.         Layout.setMargin(11)
  83.         Layout.setSpacing(6)
  84.  
  85.         self.PromptTextLabel = QLabel(self)
  86.         Layout.addWidget(self.PromptTextLabel,0,0,1,3)
  87.  
  88.         self.UsernameTextLabel = QLabel(self)
  89.         Layout.addWidget(self.UsernameTextLabel,1,0)
  90.  
  91.         self.UsernameLineEdit = QLineEdit(self)
  92.         self.UsernameLineEdit.setEchoMode(QLineEdit.Normal)
  93.         Layout.addWidget(self.UsernameLineEdit,1,1,1,2)
  94.  
  95.         self.PasswordTextLabel = QLabel(self)
  96.         Layout.addWidget(self.PasswordTextLabel,2,0)
  97.  
  98.         self.PasswordLineEdit = QLineEdit(self)
  99.         self.PasswordLineEdit.setEchoMode(QLineEdit.Password)
  100.         Layout.addWidget(self.PasswordLineEdit,2,1,1,2)
  101.  
  102.         self.OkPushButton = QPushButton(self)
  103.         Layout.addWidget(self.OkPushButton,3,2)
  104.  
  105.         self.languageChange()
  106.  
  107.         self.resize(QSize(420,163).expandedTo(self.minimumSizeHint()))
  108.  
  109.         self.connect(self.OkPushButton, SIGNAL("clicked()"), self.accept)
  110.         self.connect(self.PasswordLineEdit, SIGNAL("returnPressed()"), self.accept)
  111.  
  112.  
  113.     def getUsername(self):
  114.         return unicode(self.UsernameLineEdit.text())
  115.  
  116.  
  117.     def getPassword(self):
  118.         return unicode(self.PasswordLineEdit.text())
  119.  
  120.  
  121.     def languageChange(self):
  122.         self.setWindowTitle(self.__tr("HP Device Manager - Enter Username/Password"))
  123.         self.PromptTextLabel.setText(self.__tr(self.prompt))
  124.         self.UsernameTextLabel.setText(self.__tr("Username:"))
  125.         self.PasswordTextLabel.setText(self.__tr("Password:"))
  126.         self.OkPushButton.setText(self.__tr("OK"))
  127.  
  128.  
  129.     def __tr(self,s,c = None):
  130.         return qApp.translate("SetupDialog",s,c)
  131.  
  132.  
  133.  
  134. def showPasswordUI(prompt):
  135.     try:
  136.         dlg = PasswordDialog(prompt, None)
  137.  
  138.         if dlg.exec_() == QDialog.Accepted:
  139.             return (dlg.getUsername(), dlg.getPassword())
  140.  
  141.     finally:
  142.         pass
  143.  
  144.     return ("", "")
  145.  
  146.  
  147.  
  148. class DeviceTableWidgetItem(QTableWidgetItem):
  149.     def __init__(self, text, device_uri):
  150.         QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
  151.         self.device_uri = device_uri
  152.  
  153.  
  154.  
  155. class SetupDialog(QDialog, Ui_Dialog):
  156.     def __init__(self, parent, param, jd_port, device_uri=None, remove=False):
  157.         QDialog.__init__(self, parent)
  158.         self.setupUi(self)
  159.  
  160.         self.param = param
  161.         self.jd_port = jd_port
  162.         self.device_uri = device_uri
  163.         self.remove = remove
  164.  
  165.         if device_uri:
  166.             log.info("Using device: %s" % device_uri)
  167.  
  168.         self.initUi()
  169.  
  170.         if self.remove:
  171.             QTimer.singleShot(0, self.showRemovePage)
  172.         else:
  173.             if self.skip_discovery:
  174.                 QTimer.singleShot(0, self.showDevicesPage)
  175.             else:
  176.                 QTimer.singleShot(0, self.showDiscoveryPage)
  177.  
  178.         cups.setPasswordCallback(showPasswordUI)
  179.  
  180.  
  181.     #
  182.     # INIT
  183.     #
  184.  
  185.     def initUi(self):
  186.         self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128')))
  187.  
  188.         # connect signals/slots
  189.         self.connect(self.CancelButton, SIGNAL("clicked()"), self.CancelButton_clicked)
  190.         self.connect(self.BackButton, SIGNAL("clicked()"), self.BackButton_clicked)
  191.         self.connect(self.NextButton, SIGNAL("clicked()"), self.NextButton_clicked)
  192.         self.connect(self.ManualGroupBox,  SIGNAL("clicked(bool)"),  self.ManualGroupBox_clicked)
  193.  
  194.         if self.remove:
  195.             self.initRemovePage()
  196.             self.max_page = 1
  197.         else:
  198.             self.initDiscoveryPage()
  199.             self.initDevicesPage()
  200.             self.initAddPrinterPage()
  201.             self.max_page = PAGE_ADD_PRINTER
  202.  
  203.     #
  204.     #  DISCOVERY PAGE
  205.     #
  206.  
  207.     def initDiscoveryPage(self):
  208.         self.UsbRadioButton.setChecked(True)
  209.         self.setUsbRadioButton(True)
  210.         self.ManualGroupBox.setChecked(False)
  211.  
  212.         self.advanced = False
  213.         self.manual = False
  214.         self.skip_discovery = False
  215.         self.discovery_method = 0
  216.         self.NetworkRadioButton.setEnabled(prop.net_build)
  217.         self.WirelessButton.setEnabled(prop.net_build)
  218.         self.ParallelRadioButton.setEnabled(prop.par_build)
  219.         self.devices = {}
  220.         self.bus = 'usb'
  221.         self.timeout = 5
  222.         self.ttl = 4
  223.         self.search = ''
  224.         self.print_test_page = False
  225.         self.device_desc = DEVICE_DESC_ALL
  226.  
  227.         if self.param:
  228.             log.info("Searching for device...")
  229.             self.manual = True
  230.             self.advanced = True
  231.             self.ManualParamLineEdit.setText(self.param)
  232.             self.JetDirectSpinBox.setValue(self.jd_port)
  233.             self.ManualGroupBox.setChecked(True)
  234.             self.DiscoveryOptionsGroupBox.setEnabled(False)
  235.  
  236.             if self.manualDiscovery():
  237.                 self.skip_discovery = True
  238.             else:
  239.                 FailureUI(self, self.__tr("<b>Device not found.</b> <p>Please make sure your printer is properly connected and powered-on."))
  240.  
  241.                 match = device.usb_pat.match(self.param)
  242.                 if match is not None:
  243.                     self.UsbRadioButton.setChecked(True)
  244.                     self.setUsbRadioButton(True)
  245.  
  246.                 else:
  247.                     match = device.dev_pat.match(self.param)
  248.                     if match is not None and prop.par_build:
  249.                         self.ParallelRadioButton.setChecked(True)
  250.                         self.setParallelRadioButton(True)
  251.  
  252.                     else:
  253.                         match = device.ip_pat.match(self.param)
  254.                         if match is not None and prop.net_build:
  255.                             self.NetworkRadioButton.setChecked(True)
  256.                             self.setNetworkRadioButton(True)
  257.  
  258.                         else:
  259.                             FailureUI(self, self.__tr("<b>Invalid manual discovery parameter.</b>"))
  260.  
  261.         elif self.device_uri: # If device URI specified on the command line, skip discovery
  262.                               # if the device URI is well-formed (but not necessarily valid)
  263.             try:
  264.                 back_end, is_hp, self.bus, model, serial, dev_file, host, zc, port = \
  265.                 device.parseDeviceURI(self.device_uri)
  266.  
  267.             except Error:
  268.                 log.error("Invalid device URI specified: %s" % self.device_uri)
  269.  
  270.             else:
  271.                 name = host
  272.                 if self.bus == 'net':
  273.                     try:
  274.                         log.debug("Trying to get hostname for device...")
  275.                         name = socket.gethostbyaddr(host)[0]
  276.                     except socket.herror:
  277.                         log.debug("Failed.")
  278.                     else:
  279.                         log.debug("Host name=%s" % name)
  280.  
  281.                 self.devices = {self.device_uri : (model, model, name)}
  282.                 self.skip_discovery = True
  283.  
  284.         # If no network or parallel, usb is only option, skip initial page...
  285.         elif not prop.par_build and not prop.net_build:
  286.             self.skip_discovery = True
  287.             self.bus = 'usb'
  288.             self.UsbRadioButton.setChecked(True)
  289.             self.setUsbRadioButton(True)
  290.  
  291.         if prop.fax_build and prop.scan_build:
  292.             self.DeviceTypeComboBox.addItem("All devices/printers", QVariant(DEVICE_DESC_ALL))
  293.             self.DeviceTypeComboBox.addItem("Single function printers only", QVariant(DEVICE_DESC_SINGLE_FUNC))
  294.             self.DeviceTypeComboBox.addItem("All-in-one/MFP devices only", QVariant(DEVICE_DESC_MULTI_FUNC))
  295.         else:
  296.             self.DeviceTypeComboBox.setEnabled(False)
  297.  
  298.         self.connect(self.AdvancedButton, SIGNAL("clicked()"), self.AdvancedButton_clicked)
  299.         self.connect(self.UsbRadioButton, SIGNAL("toggled(bool)"), self.UsbRadioButton_toggled)
  300.         self.connect(self.NetworkRadioButton, SIGNAL("toggled(bool)"), self.NetworkRadioButton_toggled)
  301.         self.connect(self.WirelessButton, SIGNAL("toggled(bool)"), self.WirelessButton_toggled)
  302.         self.connect(self.ParallelRadioButton, SIGNAL("toggled(bool)"), self.ParallelRadioButton_toggled)
  303.         self.connect(self.NetworkTTLSpinBox,  SIGNAL("valueChanged(int)"), self.NetworkTTLSpinBox_valueChanged)
  304.         self.connect(self.NetworkTimeoutSpinBox,  SIGNAL("valueChanged(int)"),
  305.                      self.NetworkTimeoutSpinBox_valueChanged)
  306.         self.connect(self.ManualGroupBox,  SIGNAL("toggled(bool)"),  self.ManualGroupBox_toggled)
  307.  
  308.         self.showAdvanced()
  309.  
  310.  
  311.     def ManualGroupBox_toggled(self, checked):
  312.         self.DiscoveryOptionsGroupBox.setEnabled(not checked)
  313.  
  314.  
  315.     def manualDiscovery(self):
  316.         # Validate param...
  317.         device_uri, sane_uri, fax_uri = device.makeURI(self.param, self.jd_port)
  318.  
  319.         if device_uri:
  320.             log.info("Found device: %s" % device_uri)
  321.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
  322.                 device.parseDeviceURI(device_uri)
  323.  
  324.             name = host
  325.             if bus == 'net':
  326.                 try:
  327.                     name = socket.gethostbyaddr(host)[0]
  328.                 except (socket.herror, socket.gaierror):
  329.                     pass
  330.  
  331.             self.devices = {device_uri : (model, model, name)}
  332.  
  333.             if bus == 'usb':
  334.                 self.UsbRadioButton.setChecked(True)
  335.                 self.setUsbRadioButton(True)
  336.  
  337.             elif bus == 'net' and prop.net_build:
  338.                 self.NetworkRadioButton.setChecked(True)
  339.                 self.setNetworkRadioButton(True)
  340.  
  341.             elif bus == 'par' and prop.par_build:
  342.                 self.ParallelRadioButton.setChecked(True)
  343.                 self.setParallelRadioButton(True)
  344.  
  345.             return True
  346.  
  347.  
  348.         return False
  349.  
  350.  
  351.     def ManualGroupBox_clicked(self, checked):
  352.         self.manual = checked
  353.         network = self.NetworkRadioButton.isChecked()
  354.         self.setJetDirect(network)
  355.  
  356.  
  357.     def showDiscoveryPage(self):
  358.         self.BackButton.setEnabled(False)
  359.         self.NextButton.setEnabled(True)
  360.         self.setNextButton(BUTTON_NEXT)
  361.         self.displayPage(PAGE_DISCOVERY)
  362.  
  363.  
  364.     def AdvancedButton_clicked(self):
  365.         self.advanced = not self.advanced
  366.         self.showAdvanced()
  367.  
  368.  
  369.     def showAdvanced(self):
  370.         if self.advanced:
  371.             self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_SHOW)
  372.             self.AdvancedButton.setText(self.__tr("Hide Advanced Options"))
  373.             self.AdvancedButton.setIcon(QIcon(load_pixmap("minus", "16x16")))
  374.         else:
  375.             self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_HIDE)
  376.             self.AdvancedButton.setText(self.__tr("Show Advanced Options"))
  377.             self.AdvancedButton.setIcon(QIcon(load_pixmap("plus", "16x16")))
  378.  
  379.  
  380.     def setJetDirect(self, enabled):
  381.         self.JetDirectLabel.setEnabled(enabled and self.manual)
  382.         self.JetDirectSpinBox.setEnabled(enabled and self.manual)
  383.  
  384.  
  385.     def setNetworkOptions(self,  enabled):
  386.         self.NetworkTimeoutLabel.setEnabled(enabled)
  387.         self.NetworkTimeoutSpinBox.setEnabled(enabled)
  388.         self.NetworkTTLLabel.setEnabled(enabled)
  389.         self.NetworkTTLSpinBox.setEnabled(enabled)
  390.  
  391.  
  392.     def setSearchOptions(self, enabled):
  393.         self.SearchLineEdit.setEnabled(enabled)
  394.         self.DeviceTypeComboBox.setEnabled(enabled)
  395.         self.DeviceTypeLabel.setEnabled(enabled)
  396.  
  397.  
  398.     def setManualDiscovery(self, enabled):
  399.         self.ManualGroupBox.setEnabled(enabled)
  400.  
  401.  
  402.     def setNetworkDiscovery(self, enabled):
  403.         self.NetworkDiscoveryMethodLabel.setEnabled(enabled)
  404.         self.NetworkDiscoveryMethodComboBox.setEnabled(enabled)
  405.         self.NetworkDiscoveryMethodComboBox.setCurrentIndex(1)
  406.  
  407.  
  408.     def UsbRadioButton_toggled(self, radio_enabled):
  409.         self.setUsbRadioButton(radio_enabled)
  410.  
  411.  
  412.     def setUsbRadioButton(self, checked):
  413.         self.setNetworkDiscovery(not checked)
  414.         self.setJetDirect(not checked)
  415.         self.setNetworkOptions(not checked)
  416.         self.setSearchOptions(checked)
  417.         self.setManualDiscovery(checked)
  418.  
  419.         if checked:
  420.             self.ManualParamLabel.setText(self.__tr("USB bus ID:device ID (bbb:ddd):"))
  421.             self.bus = 'usb'
  422.             # TODO: Set bbb:ddd validator
  423.  
  424.  
  425.     def NetworkRadioButton_toggled(self, radio_enabled):
  426.         self.setNetworkRadioButton(radio_enabled)
  427.  
  428.  
  429.     def setNetworkRadioButton(self, checked):
  430.         self.setNetworkDiscovery(checked)
  431.         self.setJetDirect(checked)
  432.         self.setNetworkOptions(checked)
  433.         self.setSearchOptions(checked)
  434.         self.setManualDiscovery(checked)
  435.  
  436.  
  437.         if checked:
  438.             self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
  439.             self.bus = 'net'
  440.             # TODO: Reset validator
  441.  
  442.     def WirelessButton_toggled(self, radio_enabled):
  443.         self.setWirelessButton(radio_enabled)
  444.  
  445.  
  446.     def setWirelessButton(self, checked):
  447.         self.setNetworkDiscovery(not checked)
  448.         self.setJetDirect(not checked)
  449.         self.setNetworkOptions(not checked)
  450.         self.setSearchOptions(not checked)
  451.         self.setManualDiscovery(not checked)
  452.  
  453.  
  454.         if checked:
  455.             self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
  456.             self.bus = 'net'
  457.  
  458.  
  459.     def ParallelRadioButton_toggled(self, radio_enabled):
  460.         self.setParallelRadioButton(radio_enabled)
  461.  
  462.  
  463.     def setParallelRadioButton(self, checked):
  464.         self.setNetworkDiscovery(not checked)
  465.         self.setJetDirect(not checked)
  466.         self.setNetworkOptions(not checked)
  467.         self.setSearchOptions(not checked)
  468.         self.setManualDiscovery(not checked)
  469.  
  470.  
  471.         if checked:
  472.             self.ManualParamLabel.setText(self.__tr("Device node (/dev/...):"))
  473.             self.bus = 'par'
  474.             # TODO: Set /dev/... validator
  475.  
  476.  
  477.     def NetworkTTLSpinBox_valueChanged(self, ttl):
  478.         self.ttl = ttl
  479.  
  480.  
  481.     def NetworkTimeoutSpinBox_valueChanged(self, timeout):
  482.         self.timeout = timeout
  483.  
  484.     #
  485.     # DEVICES PAGE
  486.     #
  487.  
  488.     def initDevicesPage(self):
  489.         self.connect(self.RefreshButton,  SIGNAL("clicked()"),  self.RefreshButton_clicked)
  490.  
  491.  
  492.     def showDevicesPage(self):
  493.         self.BackButton.setEnabled(True)
  494.         self.setNextButton(BUTTON_NEXT)
  495.         search = ""
  496.  
  497.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  498.         try:
  499.             if not self.devices:
  500.                 if self.manual and self.param: # manual, but not passed-in on command line
  501.                     self.manualDiscovery()
  502.  
  503.                 else: # probe
  504.                     net_search_type = ''
  505.  
  506.                     if self.bus == 'net':
  507.                         if self.discovery_method == 0:
  508.                             net_search_type = "slp"
  509.                         else:
  510.                             net_search_type = "mdns"
  511.  
  512.                         log.info("Searching... (bus=%s, timeout=%d, ttl=%d, search=%s desc=%d, method=%s)" %
  513.                                  (self.bus,  self.timeout, self.ttl, self.search or "(None)",
  514.                                   self.device_desc, net_search_type))
  515.                     else:
  516.                         log.info("Searching... (bus=%s, search=%s, desc=%d)" %
  517.                                  (self.bus,  self.search or "(None)", self.device_desc))
  518.  
  519.                     if self.device_desc == DEVICE_DESC_SINGLE_FUNC:
  520.                         filter_dict = {'scan-type' : (operator.le, SCAN_TYPE_NONE)}
  521.  
  522.                     elif self.device_desc == DEVICE_DESC_MULTI_FUNC:
  523.                         filter_dict = {'scan-type': (operator.gt, SCAN_TYPE_NONE)}
  524.  
  525.                     else: # DEVICE_DESC_ALL
  526.                         filter_dict = {}
  527.  
  528.                     self.devices = device.probeDevices([self.bus], self.timeout, self.ttl,
  529.                                                        filter_dict, self.search, net_search=net_search_type)
  530.         finally:
  531.             QApplication.restoreOverrideCursor()
  532.  
  533.         self.clearDevicesTable()
  534.  
  535.         if self.devices:
  536.             self.NextButton.setEnabled(True)
  537.             self.DevicesFoundIcon.setPixmap(load_pixmap('info', '16x16'))
  538.  
  539.             if len(self.devices) == 1:
  540.                 self.DevicesFoundLabel.setText(self.__tr("<b>1 device found.</b> Click <i>Next</i> to continue."))
  541.             else:
  542.                 self.DevicesFoundLabel.setText(self.__tr("<b>%1 devices found.</b> Select the device to install and click <i>Next</i> to continue.").arg(len(self.devices)))
  543.  
  544.             self.loadDevicesTable()
  545.  
  546.         else:
  547.             self.NextButton.setEnabled(False)
  548.             self.DevicesFoundIcon.setPixmap(load_pixmap('error', '16x16'))
  549.             log.error("No devices found on bus: %s" % self.bus)
  550.             self.DevicesFoundLabel.setText(self.__tr("<b>No devices found.</b><br>Click <i>Back</i> to change discovery options, or <i>Refresh</i> to search again."))
  551.  
  552.         self.displayPage(PAGE_DEVICES)
  553.  
  554.  
  555.     def loadDevicesTable(self):
  556.         self.DevicesTableWidget.setRowCount(len(self.devices))
  557.  
  558.         if self.bus == 'net':
  559.             if self.discovery_method == 0:
  560.                 headers = [self.__tr('Model'), self.__tr('IP Address'), self.__tr('Host Name'), self.__tr('Device URI')]
  561.                 device_uri_col = 3
  562.             else:
  563.                 headers = [self.__tr('Model'), self.__tr('Host Name'), self.__tr('Device URI')]
  564.                 device_uri_col = 2
  565.         else:
  566.             headers = [self.__tr('Model'), self.__tr('Device URI')]
  567.             device_uri_col = 1
  568.  
  569.         self.DevicesTableWidget.setColumnCount(len(headers))
  570.         self.DevicesTableWidget.setHorizontalHeaderLabels(headers)
  571.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  572.  
  573.         for row, d in enumerate(self.devices):
  574.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(d)
  575.             model_ui = models.normalizeModelUIName(model)
  576.  
  577.             i = DeviceTableWidgetItem(QString(model_ui), d)
  578.             i.setFlags(flags)
  579.             self.DevicesTableWidget.setItem(row, 0, i)
  580.  
  581.             i = QTableWidgetItem(QString(d))
  582.             i.setFlags(flags)
  583.             self.DevicesTableWidget.setItem(row, device_uri_col, i)
  584.  
  585.             if self.bus == 'net':
  586.                 i = QTableWidgetItem(QString(host))
  587.                 i.setFlags(flags)
  588.                 self.DevicesTableWidget.setItem(row, 1, i)
  589.  
  590.                 if self.discovery_method == 0:
  591.                     i = QTableWidgetItem(QString(self.devices[d][2]))
  592.                     i.setFlags(flags)
  593.                     self.DevicesTableWidget.setItem(row, 2, i)
  594.  
  595.         self.DevicesTableWidget.resizeColumnsToContents()
  596.         self.DevicesTableWidget.selectRow(0)
  597.         self.DevicesTableWidget.setSortingEnabled(True)
  598.         self.DevicesTableWidget.sortItems(0)
  599.  
  600.  
  601.     def clearDevicesTable(self):
  602.         self.DevicesTableWidget.clear()
  603.         self.DevicesTableWidget.setRowCount(0)
  604.         self.DevicesTableWidget.setColumnCount(0)
  605.  
  606.  
  607.     def RefreshButton_clicked(self):
  608.         self.clearDevicesTable()
  609.         self.devices = []
  610.         QTimer.singleShot(0, self.showDevicesPage)
  611.  
  612.     #
  613.     # ADD PRINTER PAGE
  614.     #
  615.  
  616.     def initAddPrinterPage(self):
  617.         self.mq = {}
  618.  
  619.         self.connect(self.PrinterNameLineEdit, SIGNAL("textEdited(const QString &)"),
  620.                      self.PrinterNameLineEdit_textEdited)
  621.  
  622.         self.connect(self.FaxNameLineEdit, SIGNAL("textEdited(const QString &)"),
  623.                      self.FaxNameLineEdit_textEdited)
  624.  
  625.         self.PrinterNameLineEdit.setValidator(PrinterNameValidator(self.PrinterNameLineEdit))
  626.         self.FaxNameLineEdit.setValidator(PrinterNameValidator(self.FaxNameLineEdit))
  627.         self.FaxNumberLineEdit.setValidator(PhoneNumValidator(self.FaxNumberLineEdit))
  628.  
  629.         self.OtherPPDButton.setIcon(QIcon(load_pixmap('folder_open', '16x16')))
  630.         self.connect(self.OtherPPDButton, SIGNAL("clicked(bool)"), self.OtherPPDButton_clicked)
  631.  
  632.         self.OtherPPDButton.setToolTip(self.__tr("Browse for an alternative PPD file for this printer."))
  633.  
  634.         self.printer_fax_names_same = False
  635.         self.printer_name = ''
  636.         self.fax_name = ''
  637.         self.fax_setup_ok = True
  638.         self.fax_setup = False
  639.  
  640.  
  641.     def showAddPrinterPage(self):
  642.         # Install the plugin if needed...
  643.         core = CoreInstall()
  644.         plugin = self.mq.get('plugin', PLUGIN_NONE)
  645.         plugin_reason = self.mq.get('plugin-reason', PLUGIN_REASON_NONE)
  646.         if plugin > PLUGIN_NONE:
  647.  
  648.             if not core.check_for_plugin():
  649.                 ok, sudo_ok = pkit.run_plugin_command(plugin == PLUGIN_REQUIRED, plugin_reason)
  650.                 if not sudo_ok:
  651.                     FailureUI(self, self.__tr("<b>Unable to find an appropriate su/sudo utiltity to run hp-plugin.</b><p>Install kdesu, gnomesu, or gksu.</p>"))
  652.                     return
  653.                 if not ok or not core.check_for_plugin():
  654.                     if plugin == PLUGIN_REQUIRED:
  655.                         FailureUI(self, self.__tr("<b>The printer you are trying to setup requires a binary driver plug-in and it failed to install.</b><p>Please check your internet connection and try again.</p><p>Visit <u>http://hplipopensource.com</u> for more infomation.</p>"))
  656.                         return
  657.                     else:
  658.                         WarningUI(self, self.__tr("Either you have chosen to skip the installation of the optional plug-in or that installation has failed.  Your printer may not function at optimal performance."))
  659.  
  660.         self.setNextButton(BUTTON_ADD_PRINTER)
  661.  
  662.         if not self.printer_name:
  663.             self.setDefaultPrinterName()
  664.  
  665.         self.findPrinterPPD()
  666.  
  667.         if fax_import_ok and prop.fax_build and \
  668.             self.mq.get('fax-type', FAX_TYPE_NONE) not in (FAX_TYPE_NONE, FAX_TYPE_NOT_SUPPORTED):
  669.  
  670.             self.fax_setup = True
  671.             self.SetupFaxGroupBox.setChecked(True)
  672.             self.SetupFaxGroupBox.setEnabled(True)
  673.  
  674.             if not self.fax_name:
  675.                 self.setDefaultFaxName()
  676.  
  677.             self.findFaxPPD()
  678.  
  679.             self.readwriteFaxInformation()
  680.  
  681.         else:
  682.             self.SetupFaxGroupBox.setChecked(False)
  683.             self.SetupFaxGroupBox.setEnabled(False)
  684.             self.fax_name = ''
  685.             self.fax_name_ok = True
  686.             self.fax_setup = False
  687.             self.fax_setup_ok = True
  688.  
  689.         self.updatePPD()
  690.         self.setAddPrinterButton()
  691.         self.displayPage(PAGE_ADD_PRINTER)
  692.  
  693.  
  694.  
  695.  
  696.     def updatePPD(self):
  697.         if self.print_ppd is None:
  698.             log.error("No appropriate print PPD file found for model %s" % self.model)
  699.             self.PPDFileLineEdit.setText(self.__tr('(Not found. Click browse button to select a PPD file.)'))
  700.             try:
  701.                 self.PPDFileLineEdit.setStyleSheet("background-color: yellow")
  702.             except AttributeError:
  703.                 pass
  704.             self.PrinterDescriptionLineEdit.setText(QString(""))
  705.  
  706.         else:
  707.             self.PPDFileLineEdit.setText(self.print_ppd[0])
  708.             self.PrinterDescriptionLineEdit.setText(self.print_ppd[1])
  709.             try:
  710.                 self.PPDFileLineEdit.setStyleSheet("")
  711.             except AttributeError:
  712.                 pass
  713.  
  714.  
  715.     def OtherPPDButton_clicked(self, b):
  716.         ppd_file = unicode(QFileDialog.getOpenFileName(self, self.__tr("Select PPD File"),
  717.                                                        sys_conf.get('dirs', 'ppd'),
  718.                                                        self.__tr("PPD Files (*.ppd *.ppd.gz);;All Files (*)")))
  719.  
  720.         if ppd_file and os.path.exists(ppd_file):
  721.             self.print_ppd = (ppd_file, cups.getPPDDescription(ppd_file))
  722.             self.updatePPD()
  723.             self.setAddPrinterButton()
  724.  
  725.  
  726.     def findPrinterPPD(self):
  727.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  728.         try:
  729.             self.print_ppd = None
  730.             self.ppds = cups.getSystemPPDs()
  731.             model = cups.stripModel2(self.model)
  732.             self.print_ppd = cups.getPPDFile2(model, self.ppds)
  733.         finally:
  734.             QApplication.restoreOverrideCursor()
  735.  
  736.  
  737.     def findFaxPPD(self):
  738.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  739.         try:
  740.             log.debug("Searching for fax PPD for model %s" % self.model)
  741.  
  742.             if prop.hpcups_build:
  743.                 if self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_MARVELL:
  744.                     fax_ppd_name = "HP-Fax3-hpcups" # Fixed width (2528 pixels) and 300dpi rendering
  745.                     nick = "HP Fax3 hpcups"
  746.                 elif self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_SOAP:
  747.                     fax_ppd_name = "HP-Fax2-hpcups" # Fixed width (2528 pixels) and 300dpi rendering
  748.                     nick = "HP Fax2 hpcups"
  749.                 else:
  750.                     fax_ppd_name = "HP-Fax-hpcups" # Standard
  751.                     nick = "HP Fax hpcups"
  752.  
  753.             else: # hpijs
  754.                 if self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_MARVELL:
  755.                     fax_ppd_name = "HP-Fax3-hpijs" # Fixed width (2528 pixels) and 300dpi rendering
  756.                     nick = "HP Fax3 hpijs"
  757.                 if self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_SOAP:
  758.                     fax_ppd_name = "HP-Fax2-hpijs" # Fixed width (2528 pixels) and 300dpi rendering
  759.                     nick = "HP Fax2 hpijs"
  760.                 else:
  761.                     fax_ppd_name = "HP-Fax-hpijs" # Standard
  762.                     nick = "HP Fax hpijs"
  763.  
  764.             ppds = []
  765.  
  766.             for f in utils.walkFiles(sys_conf.get('dirs', 'ppd'), pattern="HP-Fax*.ppd*", abs_paths=True):
  767.                 ppds.append(f)
  768.  
  769.             for f in ppds:
  770.                 if f.find(fax_ppd_name) >= 0 and cups.getPPDDescription(f) == nick:
  771.                     self.fax_ppd = f
  772.                     self.fax_setup_ok = True
  773.                     log.debug("Found fax PPD: %s" % f)
  774.                     break
  775.             else:
  776.                 self.fax_ppd = None
  777.                 self.fax_setup_ok = False
  778.                 FailureUI(self, self.__tr("<b>Unable to locate the HPLIP Fax PPD file:</b><p>%1.ppd.gz</p><p>Fax setup has been disabled.").arg(fax_ppd_name))
  779.                 self.fax_setup = False
  780.                 self.SetupFaxGroupBox.setChecked(False)
  781.                 self.SetupFaxGroupBox.setEnabled(False)
  782.  
  783.         finally:
  784.             QApplication.restoreOverrideCursor()
  785.  
  786.  
  787.  
  788.     def setDefaultPrinterName(self):
  789.         self.installed_print_devices = device.getSupportedCUPSDevices(['hp'])
  790.         log.debug(self.installed_print_devices)
  791.  
  792.         self.installed_queues = [p.name for p in cups.getPrinters()]
  793.  
  794.         back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
  795.         default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  796.  
  797.         printer_name = default_model
  798.  
  799.         # Check for duplicate names
  800.         if self.device_uri in self.installed_print_devices and \
  801.             printer_name in self.installed_print_devices[self.device_uri]:
  802.                 i = 2
  803.                 while True:
  804.                     t = printer_name + "_%d" % i
  805.                     if t not in self.installed_print_devices[self.device_uri]:
  806.                         printer_name += "_%d" % i
  807.                         break
  808.                     i += 1
  809.  
  810.         self.printer_name_ok = True
  811.         self.PrinterNameLineEdit.setText(printer_name)
  812.         log.debug(printer_name)
  813.         self.printer_name = printer_name
  814.  
  815.  
  816.     def setDefaultFaxName(self):
  817.         self.installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])
  818.         log.debug(self.installed_fax_devices)
  819.  
  820.         self.fax_uri = self.device_uri.replace('hp:', 'hpfax:')
  821.  
  822.         back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.fax_uri)
  823.         default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  824.  
  825.         fax_name = default_model + "_fax"
  826.  
  827.         # Check for duplicate names
  828.         if self.fax_uri in self.installed_fax_devices and \
  829.             fax_name in self.installed_fax_devices[self.fax_uri]:
  830.                 i = 2
  831.                 while True:
  832.                     t = fax_name + "_%d" % i
  833.                     if t not in self.installed_fax_devices[self.fax_uri]:
  834.                         fax_name += "_%d" % i
  835.                         break
  836.                     i += 1
  837.  
  838.         self.fax_name_ok = True
  839.         self.FaxNameLineEdit.setText(fax_name)
  840.         self.fax_name = fax_name
  841.  
  842.  
  843.     def PrinterNameLineEdit_textEdited(self, t):
  844.         self.printer_name = unicode(t)
  845.         self.printer_name_ok = True
  846.  
  847.         if not self.printer_name:
  848.             self.PrinterNameLineEdit.setToolTip(self.__tr('You must enter a name for the printer.'))
  849.             self.printer_name_ok = False
  850.  
  851.         elif self.fax_name == self.printer_name:
  852.             s = self.__tr('The printer name and fax name must be different. Please choose different names.')
  853.             self.PrinterNameLineEdit.setToolTip(s)
  854.             self.FaxNameLineEdit.setToolTip(s)
  855.             self.fax_name_ok = False
  856.             self.printer_name_ok = False
  857.             self.printer_fax_names_same = True
  858.  
  859.         elif self.printer_name in self.installed_queues:
  860.             self.PrinterNameLineEdit.setToolTip(self.__tr('A printer already exists with this name. Please choose a different name.'))
  861.             self.printer_name_ok = False
  862.  
  863.         elif self.printer_fax_names_same:
  864.             if self.fax_name != self.printer_name:
  865.                 self.printer_fax_names_same = False
  866.                 self.printer_name_ok = True
  867.  
  868.                 self.FaxNameLineEdit.emit(SIGNAL("textChanged(const QString &)"),
  869.                             (self.FaxNameLineEdit.text(),))
  870.  
  871.         self.setIndicators()
  872.         self.setAddPrinterButton()
  873.  
  874.  
  875.     def FaxNameLineEdit_textEdited(self, t):
  876.         self.fax_name = unicode(t)
  877.         self.fax_name_ok = True
  878.  
  879.         if not self.fax_name:
  880.             self.FaxNameLineEdit.setToolTip(self.__tr('You must enter a fax name.'))
  881.             self.fax_name_ok = False
  882.  
  883.         elif self.fax_name == self.printer_name:
  884.             s = self.__tr('The printer name and fax name must be different. Please choose different names.')
  885.             self.PrinterNameLineEdit.setToolTip(s)
  886.             self.FaxNameLineEdit.setToolTip(s)
  887.             self.printer_name_ok = False
  888.             self.fax_name_ok = False
  889.             self.printer_fax_names_same = True
  890.  
  891.         elif self.fax_name in self.installed_queues:
  892.             self.FaxNameLineEdit.setToolTip(self.__tr('A fax already exists with this name. Please choose a different name.'))
  893.             self.fax_name_ok = False
  894.  
  895.         elif self.printer_fax_names_same:
  896.             if self.fax_name != self.printer_name:
  897.                 self.printer_fax_names_same = False
  898.                 self.fax_name_ok = True
  899.  
  900.                 self.PrinterNameLineEdit.emit(SIGNAL("textChanged(const QString&)"),
  901.                             (self.PrinterNameLineEdit.text(),))
  902.  
  903.         self.setIndicators()
  904.         self.setAddPrinterButton()
  905.  
  906.  
  907.     def setIndicators(self):
  908.         if self.printer_name_ok:
  909.             self.PrinterNameLineEdit.setToolTip(QString(""))
  910.             try:
  911.                 self.PrinterNameLineEdit.setStyleSheet("")
  912.             except AttributeError:
  913.                 pass
  914.         else:
  915.             try:
  916.                 self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
  917.             except AttributeError:
  918.                 pass
  919.  
  920.         if self.fax_name_ok:
  921.             self.FaxNameLineEdit.setToolTip(QString(""))
  922.             try:
  923.                 self.PrinterNameLineEdit.setStyleSheet("")
  924.             except AttributeError:
  925.                 pass
  926.         else:
  927.             try:
  928.                 self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
  929.             except AttributeError:
  930.                 pass
  931.  
  932.  
  933.     def setAddPrinterButton(self):
  934.         self.NextButton.setEnabled((self.printer_name_ok and self.print_ppd is not None) and
  935.                                    ((self.fax_setup and self.fax_name_ok) or not self.fax_setup))
  936.  
  937.  
  938.     #
  939.     # ADD PRINTER
  940.     #
  941.  
  942.     def addPrinter(self):
  943.         self.setupPrinter()
  944.  
  945.         if self.fax_setup:
  946.             self.setupFax()
  947.             self.readwriteFaxInformation(False)
  948.  
  949.         if self.print_test_page:
  950.             self.printTestPage()
  951.  
  952.         self.close()
  953.  
  954.  
  955.  
  956.     #
  957.     # SETUP PRINTER/FAX
  958.     #
  959.  
  960.     def setupPrinter(self):
  961.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  962.         try:
  963.             cups.setPasswordPrompt("You do not have permission to add a printer.")
  964.             if not os.path.exists(self.print_ppd[0]): # assume foomatic: or some such
  965.                 status, status_str = cups.addPrinter(self.printer_name.encode('utf8'), self.device_uri,
  966.                     self.print_location, '', self.print_ppd[0], self.print_desc)
  967.             else:
  968.                 status, status_str = cups.addPrinter(self.printer_name.encode('utf8'), self.device_uri,
  969.                     self.print_location, self.print_ppd[0], '', self.print_desc)
  970.  
  971.             log.debug("addPrinter() returned (%d, %s)" % (status, status_str))
  972.             self.installed_print_devices = device.getSupportedCUPSDevices(['hp'])
  973.  
  974.             log.debug(self.installed_print_devices)
  975.  
  976.             if self.device_uri not in self.installed_print_devices or \
  977.                 self.printer_name not in self.installed_print_devices[self.device_uri]:
  978.  
  979.                 QApplication.restoreOverrideCursor()
  980.                 FailureUI(self, self.__tr("<b>Printer queue setup failed.</b><p>Please restart CUPS and try again."))
  981.             else:
  982.                 # TODO:
  983.                 #service.sendEvent(self.hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=self.device_uri)
  984.                 pass
  985.  
  986.         finally:
  987.             QApplication.restoreOverrideCursor()
  988.  
  989.  
  990.     def setupFax(self):
  991.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  992.         try:
  993.             cups.setPasswordPrompt("You do not have permission to add a fax device.")
  994.             if not os.path.exists(self.fax_ppd):
  995.                 status, status_str = cups.addPrinter(self.fax_name.encode('utf8'),
  996.                     self.fax_uri, self.fax_location, '', self.fax_ppd,  self.fax_desc)
  997.             else:
  998.                 status, status_str = cups.addPrinter(self.fax_name.encode('utf8'),
  999.                     self.fax_uri, self.fax_location, self.fax_ppd, '', self.fax_desc)
  1000.  
  1001.             log.debug("addPrinter() returned (%d, %s)" % (status, status_str))
  1002.             self.installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])
  1003.  
  1004.             log.debug(self.installed_fax_devices)
  1005.  
  1006.             if self.fax_uri not in self.installed_fax_devices or \
  1007.                 self.fax_name not in self.installed_fax_devices[self.fax_uri]:
  1008.  
  1009.                 QApplication.restoreOverrideCursor()
  1010.                 FailureUI(self, self.__tr("<b>Fax queue setup failed.</b><p>Please restart CUPS and try again."))
  1011.             else:
  1012.                 pass
  1013.                 # TODO:
  1014.                 #service.sendEvent(self.hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=self.fax_uri)
  1015.  
  1016.         finally:
  1017.             QApplication.restoreOverrideCursor()
  1018.  
  1019.  
  1020.     def readwriteFaxInformation(self, read=True):
  1021.         try:
  1022.             QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  1023.  
  1024.             d = fax.getFaxDevice(self.fax_uri, disable_dbus=True)
  1025.  
  1026.             while True:
  1027.                 try:
  1028.                     d.open()
  1029.                 except Error:
  1030.                     error_text = self.__tr("Unable to communicate with the device. Please check the device and try again.")
  1031.                     log.error(unicode(error_text))
  1032.                     if QMessageBox.critical(self,
  1033.                                            self.windowTitle(),
  1034.                                            error_text,
  1035.                                            QMessageBox.Retry | QMessageBox.Default,
  1036.                                            QMessageBox.Cancel | QMessageBox.Escape,
  1037.                                            QMessageBox.NoButton) == QMessageBox.Cancel:
  1038.                         break
  1039.  
  1040.                 else:
  1041.                     try:
  1042.                         tries = 0
  1043.                         ok = True
  1044.  
  1045.                         while True:
  1046.                             tries += 1
  1047.  
  1048.                             try:
  1049.                                 if read:
  1050.                                     self.fax_number = unicode(d.getPhoneNum())
  1051.                                     self.fax_name_company = unicode(d.getStationName())
  1052.                                 else:
  1053.                                     d.setStationName(self.fax_name_company)
  1054.                                     d.setPhoneNum(self.fax_number)
  1055.  
  1056.                             except Error:
  1057.                                 error_text = self.__tr("<b>Device I/O Error</b><p>Could not communicate with device. Device may be busy.")
  1058.                                 log.error(unicode(error_text))
  1059.  
  1060.                                 if QMessageBox.critical(self,
  1061.                                                        self.windowTitle(),
  1062.                                                        error_text,
  1063.                                                        QMessageBox.Retry | QMessageBox.Default,
  1064.                                                        QMessageBox.Cancel | QMessageBox.Escape,
  1065.                                                        QMessageBox.NoButton) == QMessageBox.Cancel:
  1066.                                     break
  1067.  
  1068.  
  1069.                                 time.sleep(5)
  1070.                                 ok = False
  1071.  
  1072.                                 if tries > 12:
  1073.                                     break
  1074.  
  1075.                             else:
  1076.                                 ok = True
  1077.                                 break
  1078.  
  1079.                     finally:
  1080.                         d.close()
  1081.  
  1082.                     if ok and read:
  1083.                         self.FaxNumberLineEdit.setText(self.fax_number)
  1084.                         self.NameCompanyLineEdit.setText(self.fax_name_company)
  1085.  
  1086.                     break
  1087.  
  1088.         finally:
  1089.             QApplication.restoreOverrideCursor()
  1090.  
  1091.  
  1092.     def printTestPage(self):
  1093.         try:
  1094.             d = device.Device(self.device_uri)
  1095.         except Error, e:
  1096.             FailureUI(self, self.__tr("<b>Device error:</b><p>%s (%s)." % (e.msg, e.opt)))
  1097.  
  1098.         else:
  1099.             try:
  1100.                 d.open()
  1101.             except Error:
  1102.                 FailureUI(self, self.__tr("<b>Unable to print to printer.</b><p>Please check device and try again."))
  1103.             else:
  1104.                 if d.isIdleAndNoError():
  1105.                     d.close()
  1106.  
  1107.                     try:
  1108.                         d.printTestPage(self.printer_name)
  1109.                     except Error, e:
  1110.                         if e.opt == ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE:
  1111.                             FailureUI(self, self.__tr("<b>No CUPS queue found for device.</b><p>Please install the printer in CUPS and try again."))
  1112.                         else:
  1113.                             FailureUI(self, self.__tr("<b>Printer Error</b><p>An error occured: %s (code=%d)." % (e.msg, e.opt)))
  1114.                 else:
  1115.                     FailureUI(self, self.__tr("<b>Printer Error.</b><p>Printer is busy, offline, or in an error state. Please check the device and try again."))
  1116.                     d.close()
  1117.  
  1118.     #
  1119.     # Remove Page
  1120.     #
  1121.  
  1122.     def initRemovePage(self):
  1123.         pass
  1124.  
  1125.  
  1126.     def showRemovePage(self):
  1127.         self.displayPage(PAGE_REMOVE)
  1128.         self.StepText.setText(self.__tr("Step 1 of 1"))
  1129.         self.setNextButton(BUTTON_REMOVE)
  1130.         self.BackButton.setEnabled(False)
  1131.         self.NextButton.setEnabled(False)
  1132.  
  1133.         self.RemoveDevicesTableWidget.verticalHeader().hide()
  1134.  
  1135.         self.installed_printers = device.getSupportedCUPSPrinters(['hp', 'hpfax'])
  1136.         log.debug(self.installed_printers)
  1137.  
  1138.         if not self.installed_printers:
  1139.             FailureUI(self, self.__tr("<b>No printers or faxes found to remove.</b><p>You must setup a least one printer or fax before you can remove it."))
  1140.             self.close()
  1141.             return
  1142.  
  1143.         self.RemoveDevicesTableWidget.setRowCount(len(self.installed_printers))
  1144.  
  1145.         headers = [self.__tr("Select"), self.__tr('Printer (Queue) Name'), self.__tr('Type'), self.__tr('Device URI')]
  1146.  
  1147.         self.RemoveDevicesTableWidget.setColumnCount(len(headers))
  1148.         self.RemoveDevicesTableWidget.setHorizontalHeaderLabels(headers)
  1149.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  1150.  
  1151.         row = 0
  1152.         for p in self.installed_printers:
  1153.             widget = QCheckBox(self.RemoveDevicesTableWidget)
  1154.             self.connect(widget, SIGNAL("stateChanged(int)"), self.CheckBox_stateChanged)
  1155.             self.RemoveDevicesTableWidget.setCellWidget(row, 0, widget)
  1156.  
  1157.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
  1158.                 device.parseDeviceURI(p.device_uri)
  1159.  
  1160.             if self.device_uri is not None and self.device_uri == p.device_uri:
  1161.                 widget.setCheckState(Qt.Checked)
  1162.  
  1163.             i = QTableWidgetItem(QString(p.name))
  1164.             i.setFlags(flags)
  1165.             i.setData(Qt.UserRole, QVariant(p.name))
  1166.             self.RemoveDevicesTableWidget.setItem(row, 1, i)
  1167.  
  1168.             if back_end == 'hpfax':
  1169.                 typ = self.__tr("Fax")
  1170.             else:
  1171.                 typ = self.__tr("Printer")
  1172.  
  1173.             i = QTableWidgetItem(typ)
  1174.             i.setFlags(flags)
  1175.             self.RemoveDevicesTableWidget.setItem(row, 2, i)
  1176.  
  1177.             i = QTableWidgetItem(QString(p.device_uri))
  1178.             i.setFlags(flags)
  1179.             self.RemoveDevicesTableWidget.setItem(row, 3, i)
  1180.  
  1181.             row += 1
  1182.  
  1183.         self.RemoveDevicesTableWidget.resizeColumnsToContents()
  1184.  
  1185.  
  1186.     def CheckBox_stateChanged(self, i):
  1187.         for row in xrange(self.RemoveDevicesTableWidget.rowCount()):
  1188.             widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
  1189.             if widget.checkState() == Qt.Checked:
  1190.                 self.NextButton.setEnabled(True)
  1191.                 break
  1192.         else:
  1193.             self.NextButton.setEnabled(False)
  1194.  
  1195.  
  1196.     #
  1197.     # Misc
  1198.     #
  1199.  
  1200.     def NextButton_clicked(self):
  1201.         p = self.StackedWidget.currentIndex()
  1202.         if p == PAGE_DISCOVERY:
  1203.             self.manual = self.ManualGroupBox.isChecked()
  1204.             self.param = unicode(self.ManualParamLineEdit.text())
  1205.             self.jd_port = self.JetDirectSpinBox.value()
  1206.             self.search = unicode(self.SearchLineEdit.text())
  1207.             self.device_desc = int(self.DeviceTypeComboBox.itemData(self.DeviceTypeComboBox.currentIndex()).toInt()[0])
  1208.             self.discovery_method = self.NetworkDiscoveryMethodComboBox.currentIndex()
  1209.  
  1210.             if self.WirelessButton.isChecked():
  1211.                 dlg = WifiSetupDialog(self, device_uri=None, standalone=False)
  1212.                 dlg.exec_()
  1213.  
  1214.                 if dlg.success == SUCCESS_CONNECTED:
  1215.                     self.manual = True
  1216.                     self.param = dlg.hn
  1217.                     self.bus = 'net'
  1218.  
  1219.             self.showDevicesPage()
  1220.  
  1221.         elif p == PAGE_DEVICES:
  1222.             row = self.DevicesTableWidget.currentRow()
  1223.             self.device_uri = self.DevicesTableWidget.item(row, 0).device_uri
  1224.             self.mq = device.queryModelByURI(self.device_uri)
  1225.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
  1226.             self.model = models.normalizeModelName(model).lower()
  1227.             self.showAddPrinterPage()
  1228.  
  1229.         elif p == PAGE_ADD_PRINTER:
  1230.             self.print_test_page = self.SendTestPageCheckBox.isChecked()
  1231.             self.print_desc = unicode(self.PrinterDescriptionLineEdit.text()).encode('utf8')
  1232.             self.print_location = unicode(self.PrinterLocationLineEdit.text()).encode('utf8')
  1233.             self.fax_setup = self.SetupFaxGroupBox.isChecked()
  1234.             self.fax_desc = unicode(self.FaxDescriptionLineEdit.text()).encode('utf8')
  1235.             self.fax_location = unicode(self.FaxLocationLineEdit.text()).encode('utf8')
  1236.             self.fax_name_company = unicode(self.NameCompanyLineEdit.text()).encode('utf8')
  1237.             self.fax_number = unicode(self.FaxNumberLineEdit.text()).encode('utf8')
  1238.             self.addPrinter()
  1239.  
  1240.         elif p == PAGE_REMOVE:
  1241.             for row in xrange(self.RemoveDevicesTableWidget.rowCount()):
  1242.                 widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
  1243.                 if widget.checkState() == Qt.Checked:
  1244.                     item = self.RemoveDevicesTableWidget.item(row, 1)
  1245.                     printer = unicode(item.data(Qt.UserRole).toString()).encode('utf-8')
  1246.                     log.debug("Removing printer: %s" % printer)
  1247.                     r = cups.delPrinter(printer)
  1248.                     if r == 0:
  1249.                         FailureUI(self, self.__tr("<b>Unable to delete printer.</b><p>Try after adding user to \"lpadmin\" or \"sys\" or \"lp\" group."))
  1250.             self.close()
  1251.  
  1252.         else:
  1253.             log.error("Invalid page!") # shouldn't happen!
  1254.  
  1255.  
  1256.     def BackButton_clicked(self):
  1257.         p = self.StackedWidget.currentIndex()
  1258.         if p == PAGE_DEVICES:
  1259.             self.devices = {}
  1260.             self.showDiscoveryPage()
  1261.  
  1262.         elif p == PAGE_ADD_PRINTER:
  1263.             self.showDevicesPage()
  1264.  
  1265.         else:
  1266.             log.error("Invalid page!") # shouldn't happen!
  1267.  
  1268.  
  1269.     def CancelButton_clicked(self):
  1270.         self.close()
  1271.  
  1272.  
  1273.     def displayPage(self, page):
  1274.         self.StackedWidget.setCurrentIndex(page)
  1275.         self.updateStepText(page)
  1276.  
  1277.  
  1278.     def setNextButton(self, typ=BUTTON_FINISH):
  1279.         if typ == BUTTON_ADD_PRINTER:
  1280.             self.NextButton.setText(self.__tr("Add Printer"))
  1281.         elif typ == BUTTON_NEXT:
  1282.             self.NextButton.setText(self.__tr("Next >"))
  1283.         elif typ == BUTTON_FINISH:
  1284.             self.NextButton.setText(self.__tr("Finish"))
  1285.         elif typ == BUTTON_REMOVE:
  1286.             self.NextButton.setText(self.__tr("Remove"))
  1287.  
  1288.  
  1289.     def updateStepText(self, p):
  1290.         self.StepText.setText(self.__tr("Step %1 of %2").arg(p+1).arg(self.max_page+1))
  1291.  
  1292.  
  1293.     def __tr(self,s,c = None):
  1294.         return qApp.translate("SetupDialog",s,c)
  1295.  
  1296.  
  1297.